from datetime import datetime
import random
import re
from flask import request, abort, current_app, make_response, json, jsonify, session
from infos.lib.yuntongxun.sms import CCP
from infos.models import User
from infos.modules.passport import passport_blu
from infos import redis_store, constants, db
from infos.utils.captcha import captcha
from infos.utils.response_code import RET

# 退出
@passport_blu.route('/logout')
def logout():
    """
        点击退出清除用户缓存信息
    :return:
    """
    session.pop('user_id',None)
    session.pop('mobile',None)
    session.pop('nike_name',None)
    return jsonify(errno=RET.OK,errmsg='OK')
# 登录
@passport_blu.route('/login',methods=['POST'])
def log_in():
    """
        1.获取参数
        2.检查参数完整性
        3.检查手机号格式
        4.在数据库中查询手机号和密码
        5.提交登录时间到数据库
        6.返回登录成功
    :return:
    """
    # 1.获取参数
    mobile = request.json.get('mobile')
    password = request.json.get('passport')

    # 2.检查参数完整性
    if not all([mobile, password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')
    # 3.检查手机号格式
    if not re.match('1[35678]\\d{9}', mobile):
        return jsonify(errno=RET.PARAMERR, errmsg='手机号格式错误')
    # 4.在数据库中查询手机号和密码
    try:
        user = User.query.filter(User.mobile==mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='查询数据异常')
    if user is None or not user.check_passowrd(password):
        return jsonify(errno=RET.PARAMERR,errmsg='用户名或密码错误')
    #记录登录时间
    user.last_login = datetime.now()
    # 5.提交登录时间到数据库
    # try:
    #     db.session.commit()
    # except Exception as e:
    #     current_app.logger.error(e)
    #     db.session.rollback()
    #     return jsonify(errno=RET.DBERR,errmsg='数据库错误')

    #用户信息缓存到redis数据库中
    session['user_id'] = user.id
    session['nick_name'] = mobile
    session['mobile'] = mobile
    # 6.返回结果
    return jsonify(errno=RET.OK,errmsg='登录成功')
# 注册
@passport_blu.route('/register',methods=['POST'])
def register():
    """
        1.获取参数,mobile,sms_code,password
        2.检查参数完整性
        3.检查手机号格式
        4.获取本地存储的真实短信验证码
        5.判断短信验证码是否存在
        6.先比较短信验证码是否正确
        7.删除redis中的验证码
        8.判断手机号是否注册
        9.实例化模型类对象，保存用户的登录信息
       10.提交数据导数据库，如果发生异常需要回滚
       11.把用户基本信息存入redis缓存中
       12.返回结果
    :return:
    """
    # 1.获取参数
    mobile = request.json.get('mobile')
    smscode = request.json.get('smscode')
    password = request.json.get('password')

    # 2.检查参数完整性
    if not all([mobile,smscode,password]):
        return jsonify(errno=RET.PARAMERR,errmsg='参数不完整')
    # 3.检查手机号格式
    if not re.match('1[35678]\\d{9}', mobile):
        return jsonify(errno=RET.PARAMERR, errmsg='手机号格式错误')
    #  4.获取本地存储的真实短信验证码
    try:
        real_smscode = redis_store.get(mobile).decode('utf-8')
    except Exception as e:
    #  5.判断短信验证码是否存在
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询失败')
    #  6.先比较短信验证码是否正确
    if not real_smscode:
        return jsonify(errno=RET.DBERR, errmsg='验证码过期')
    if real_smscode != smscode:
        return jsonify(errno=RET.DBERR, errmsg='验证码错误')
    #  7.删除redis中的验证码
    #  8.判断手机号是否注册
    #  9.实例化模型类对象，保存用户的登录信息
    user = User()
    user.mobile = mobile
    user.nick_name = mobile
    user.last_login = datetime.now()
    # 密码加密
    user.password = password
    # 10.提交数据导数据库，如果发生异常需要回滚
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        # 提交发生异常,回滚
        db.session.rollback()
        return  jsonify(errno=RET.DBERR,errmsg='保存数据失败')
    # 11.把用户基本信息存入redis缓存中
    session['user_id'] = user.id
    session['nick_name'] = mobile
    session['mobile'] = mobile
    # 12.返回结果
    return jsonify(errno=RET.OK, errmsg='注册成功')

# 生成图片验证码
@passport_blu.route('/image_code')
def get_image():
    """
        生成图片验证码并返回
        1.取到参数
        2.判断参数是否有值
        3.生成图片验证码
        4.保证图片验证码文字内容到redis
        5.返回验证码图片
    :return:
    """
    imageCodeId = request.args.get('imageCodeId')
    print(imageCodeId)
    if not imageCodeId:
        return abort(404)
    name, text, image = captcha.captcha.generate_captcha()
    print(text)
    try:
        redis_store.set(imageCodeId, text, constants.IMAGE_CODE_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.error(e)

    response = make_response(image)
    response.headers['Content-Type'] = 'image/jpg'
    return response


# 绑定注册表单
@passport_blu.route('/sms_code', methods=['post'])
def get_sms_code():
    """
        1.获取参数mobile,image_code,image_code_id,request.json.get()
        2.判断参数完整性，三个参数必须完全存在
        3.校验参数是否正确，手机号的格式，正则校验
        4.获取本地真实图片验证码
        5.判断是否过期，如果过期则直接return
        6.删除图片验证码
        7.判断图片验证码是否正确
        8.生成六位的短信验证码随机数
        9.在redis中存储短信随机数
        10.调用云通讯发送短信，需要保持发送结果
        11.判断发送是否成功
    """
    # 1.获取手机号,图片验证码,UUID
    params_dict = request.json
    mobile = params_dict['mobile']
    # 打印手机号
    print('-->{}<--'.format(mobile))
    imageCode = params_dict['image_code']
    imageCodeId = params_dict['image_code_id']

    # 2.判断输入不能为空
    if not all([mobile, imageCode, imageCodeId]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    # 3.判断手机号格式
    if not re.match('1[35678]\\d{9}', mobile):
        return jsonify(errno=RET.PARAMERR, errmsg='手机号格式错误')
    # 4.获取本地存储的真实短信验证码
    try:
        real_image_code = redis_store.get(imageCodeId).decode('utf-8')
    except Exception as e:
    # 5.判断验证码是否过期或错误,比较短信验证码是否正确
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='验证码过期')
    if imageCode.upper() != real_image_code.upper():
        return jsonify(errno=RET.DATAERR, errmsg='验证码错误')
    # 随机一个验证码
    sms_code = '%06d' % random.randint(0, 999999)
    print(sms_code)
    # 将验证码存到redis数据库中
    try:
        redis_store.set(mobile, sms_code, ex=constants.SMS_CODE_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg='数据错误')
    # 验证码发送倒计时
    result = CCP().send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES / 60], "1")
    # 如果为-1就发送验证码失败,0则发送成功
    if result == -1:
        return jsonify(errno=RET.THIRDERR, errmsg='发送失败')
    return jsonify(errno=RET.OK, errmsg='发送成功')